package com.xueqiu.movieplaymanagersystem.utils;

import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.apache.commons.io.IOUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

/**
 * @author xueqiu
 */
public class UploadUtils {

    /**
     * 上传电影封面
     *
     * @param file             电影封面图；格式不限
     * @param requestVisitPath 服务器上电影封面图的存放路径，也是request的访问路径的一部分
     * @param request          请求
     * @return null或者电影封面图URL
     */
    public static String upload(MultipartFile file, String requestVisitPath, HttpServletRequest request) {
        String originalFilename = file.getOriginalFilename();
        //源文件名不得为空
        if (originalFilename == null) {
            return null;
        }
        int index = originalFilename.lastIndexOf(".");
        //源文件名必须拥有文件后缀
        if (index == -1) {
            return null;
        }
        String[] split = originalFilename.split("\\.");
        //源文件名称拼上UUID成为新文件名称
        String newFileName = split[0] + UUIDUtils.uuid();
        //新文件名称拼上文件类型成为要保存的文件的名称
        String saveFileName = newFileName + originalFilename.substring(index);
        //子目录名称
        String childrenDirPath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        //使用 File 类创建一个表示目录的对象;requestVisitPath 是父目录的路径，childrenDir 是子目录的名称
        File saveFile = new File(requestVisitPath, childrenDirPath);
        //如果目录已经存在，则不会创建新的目录
        saveFile.mkdir();
        try {
            //从上传的 file 对象中获取输入流，用于读取图像数据。
            InputStream inputStream = file.getInputStream();
            //创建一个 Thumbnails 对象，用于处理输入流中的图像。
            Thumbnails.of(inputStream)
                    //设置缩放比例为 1，即不缩放。
                    .scale(1f)
                    //设置输出图像的质量为 25%。
                    .outputQuality(0.25f).
                    watermark(
                            //将水印放置在图像的左下角。
                            Positions.BOTTOM_LEFT,
                            //读取水印图像 shui.png。
                            ImageIO.read(
                                    Objects.requireNonNull(
                                            UploadUtils.class.getClassLoader()
                                                    .getResourceAsStream("static/img/shui.png")
                                    )
                            ),
                            //设置水印的透明度为 50%。
                            0.5f
                    )
                    //将处理后的图像保存到指定的本地文件路径 saveFile，文件名为 saveFileName。
                    .toFile(new File(saveFile, saveFileName));
            //构建访问图像的完整 URL，使用请求的协议request.getScheme()、服务器名request.getServerName()和端口号request.getServerPort()。
            String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/";
            //childrenDirPath 和 saveFileName 用于构建文件的相对路径
            String finalUrl = url + childrenDirPath + "/" + saveFileName;
            //返回生成的 URL，去除所有空白字符。
            return StringUtils.trimAllWhitespace(finalUrl);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 上传电影媒体文件
     *
     * @param file             电影媒体文件；格式不限
     * @param requestVisitPath 服务器上电影媒体文件的存放路径，也是request的访问路径的一部分
     * @param request          请求
     * @return null或者电影媒体文件URL
     */
    public static String uploadMovie(MultipartFile file, String requestVisitPath, HttpServletRequest request) {
        String originalFilename = file.getOriginalFilename();
        //源文件名不得为空
        if (originalFilename == null) {
            return null;
        }
        int index = originalFilename.lastIndexOf(".");
        //源文件名必须拥有文件后缀
        if (index == -1) {
            return null;
        }
        //直接使用UUID当作新文件名称
        String newFileName = UUIDUtils.uuid();
        //新文件名称拼上源文件后缀名成为保存文件名称
        String saveFileName = newFileName + originalFilename.substring(index);
        //子目录名称
        String childrenDirPath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        //使用 File 类创建一个表示目录的对象;requestVisitPath 是父目录的路径，childrenDir 是子目录的名称
        File localFile = new File(requestVisitPath, childrenDirPath);
        //如果目录已经存在，则不会创建新的目录
        localFile.mkdir();
        //创建 FileOutputStream 对象，用于将数据写入 saveFilePath 指定的文件
        FileOutputStream outputStream = null;
        try {
            //组合成绝对路径
            String saveFilePath = localFile + "/" + saveFileName;
            outputStream = new FileOutputStream(saveFilePath);
            //开始文件写入到本地
            IOUtils.copy(file.getInputStream(), outputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        //构建访问媒体的完整 URL，使用请求的协议request.getScheme()、服务器名request.getServerName()和端口号request.getServerPort()。
        String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/";
        //childrenDirPath 和 saveFileName 用于构建文件的相对路径
        String finalUrl = url + childrenDirPath + "/" + saveFileName;
        //返回生成的 URL，去除所有空白字符
        return StringUtils.trimAllWhitespace(finalUrl);
    }

    /**
     * 生成水印的测试方法
     *
     * @param name 水印上的姓名
     * @param date 水印上的日期
     * @return 水印图片
     */
    public static BufferedImage handleTextWaterMark(String name, String date) {
        BufferedImage bimage = new BufferedImage(
                120,
                50,
                BufferedImage.TYPE_INT_RGB
        );
        Graphics2D g = bimage.createGraphics();
        g.setColor(Color.gray);
        g.setBackground(Color.white);
        // 添加水印的文字和设置水印文字出现的内容
        g.drawString(name + "  " + date, 100 / 5, 100 / 5);
        g.dispose();
        return bimage;
    }
    /*
    这段 Java 代码用于创建一个带有文本水印的图像。以下是详细解释：
    ### 代码解析
    1. **创建图像对象**:
       ```java
       BufferedImage bimage = new BufferedImage(
               120,
               50,
               BufferedImage.TYPE_INT_RGB
       );
       ```
       - 创建一个宽 120 像素、高 50 像素的 `BufferedImage` 对象。
       - 图像类型为 `TYPE_INT_RGB`，表示使用 RGB 颜色模型。
    2. **获取绘图对象**:
       ```java
       Graphics2D g = bimage.createGraphics();
       ```
       - 从 `BufferedImage` 中获取 `Graphics2D` 对象，用于在图像上绘制内容。
    3. **设置颜色和背景**:
       ```java
       g.setColor(Color.gray);
       g.setBackground(Color.white);
       ```
       - 设置绘制文本的颜色为灰色。
       - 设置背景色为白色（尽管 `setBackground` 不直接影响绘图，需要填充背景以应用）。
    4. **绘制文本水印**:
       ```java
       g.drawString(name + "  " + date, 100 / 5, 100 / 5);
       ```
       - 在图像上绘制文本，内容为 `name` 和 `date`。
       - 文本位置的坐标为 (20, 20)，即 `(100 / 5, 100 / 5)`。
    5. **释放资源**:
       ```java
       g.dispose();
       ```
       - 释放 `Graphics2D` 对象，释放系统资源。
    6. **返回图像**:
       ```java
       return bimage;
       ```
       - 返回生成的 `BufferedImage` 对象。
    ### 用途
    这段代码用于生成一个小型图像，其中包含指定的文本水印。可以用于在图片上标识信息，如作者名和日期。
     */
}
